#include <iostream>
//#include<gtest/gtest.h>
#include <pthread.h>
#include <thread>
#include <unistd.h>
#include <string.h>
#include <gflags/gflags.h>
#include "TCPServer.h"
#include "TCPCilent.h"
#include "LoopContrller.h"
#define TIME_OUT	5000*1000
using namespace google;
static void timer_cb(uv_timer_t *handle) 
{	
	uv_timer_init(((uv_loop_t*)handle->data), handle);
	uv_timer_start(handle, timer_cb, TIME_OUT, 0);
}
DEFINE_string(t, "s", "pragram run type ?");
DEFINE_string(ip, "0.0.0.0", "My ip ?");
//DEFINE_string(ip, "192.168.1.101", "My ip ?");
DEFINE_uint32(port, 9002, "what is the port ?");
DEFINE_uint32(interval, 0, "reconnect interval?");
DEFINE_uint32(concnt, 1, "connect count?");
void TEST_SESSION_SERVER(char*ip, size_t port);
void TEST_CLIENT(char*ip, size_t port,size_t interval,size_t conncnt);
void signal_exit(int dunno);
uv_loop_t* loop;
CTCPServerPtr svr;
int main(int argc, char **argv){
#if UNIT_TEST
	testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
#else	
	signal(SIGHUP, signal_exit);
	signal(SIGINT, signal_exit);
	signal(SIGQUIT, signal_exit);
	signal(SIGABRT, signal_exit);
	signal(SIGKILL, signal_exit);
	signal(SIGTERM, signal_exit);
	signal(SIGSEGV, signal_exit);
	
	svr = CTCPServerPtr(CTCPServer::NewTCPSvr(g_Loop));
	ParseCommandLineFlags(&argc, &argv, true);
	if (strcmp(FLAGS_t.c_str(), "s") == 0){	
		TEST_SESSION_SERVER((char*)FLAGS_ip.c_str(), FLAGS_port);
	}
	else if (strcmp(FLAGS_t.c_str(), "c") == 0)
	{
		TEST_CLIENT((char*)FLAGS_ip.c_str(), FLAGS_port, FLAGS_interval,FLAGS_concnt);
	}
	else{
		printf("can not find run type\n");
	}
	g_LoopContr.StartRun();	
	return 0;
#endif
}
static CTCPClientPtr arry[100000] = { 0 };
static char* msg = "helloworld";
void TEST_CLIENT(char*ip, size_t port, size_t interval,size_t cnt){
	if (cnt>100000){
		printf("can not support 100000 connect\n");
		return;
	}	
	for (int i = 0; i < cnt; i++)
	{
		CTCPClientPtr client(CTCPClient::NewTCPClien(g_Loop));
		arry[i] = client;
		client->OnConnStatus([](CTCPClientPtr clit, int status){
			if (status == 0){				
				clit->OnMsgCall([&](SessionPtr session, char* szByte, int len) {					
					szByte[6] = 0;
					//printf("rev szByte %s\n", szByte);
					std::string s(szByte);
					//session->Write((char*)s.c_str(), s.length());					
					if (memcmp(szByte, "exit", 4) == 0){
						session->CloseSession();
					}
				});
				clit->OnClose([](SessionPtr session){
					printf("tcp close\n");
				});
				clit->Write(msg, strlen(msg));
			}
		});
		client->SetReConnInteral(interval);
		client->Connect(ip, port);
		usleep(10);
	}	
}
void TEST_SESSION_SERVER(char*ip ,size_t port){		
	svr->OnMsgCall([&](SessionPtr session, char* szByte, int len){		
		std::string s(szByte);
		if (memcmp(szByte, "server stop",10) == 0){
			svr->StopServer();
		}
		else{			
			session->Write((char*)s.c_str(), s.length());
		}		
	});
	svr->StartServer(ip, port);	
}

void signal_exit(int dunno)
{
	char* signal_str = "";
	char dunno_str[10] = { 0 };
	sprintf(dunno_str, "%d", dunno);
	switch (dunno)
	{
	case 1:
		signal_str = "SIGHUP(1)";
		break;
	case 2:
		signal_str = "SIGINT(2:CTRL_C)"; //CTRL_C
		{
			if (strcmp(FLAGS_t.c_str(), "c") == 0){				
				for (int i = 0; i < FLAGS_concnt; i++)
				{
					arry[i]->CloseConn();					
					printf("close client cnt %d\n", i);
				}					
			}
			else
			{
				svr->StopServer();
			}
			g_LoopContr.StopRun();
							
		}		
		break;
	case 3:
		signal_str = "SIGQUIT(3)";
		break;
	case 6:
	{
		signal_str = "SIGABRT(6)";
		//out_stack(signal_str);
	}
	break;
	case 9:
		signal_str = "SIGKILL(9)";
		break;
	case 15:
		signal_str = "SIGTERM(15 KILL)"; //kill 
		exit(0);
		break;
	case 11:
	{
		signal_str = "SIGSEGV(11)"; //SIGSEGV 
		//out_stack(signal_str);
	}
	break;
	default:
		signal_str = "OTHER";
		break;
	}	
}